using System;
using System.Drawing;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace OhioState.Graphics.Proxy
{

    
    /// <summary>
    /// Class for reading multiple segments of data in png format
    /// </summary>
    [Serializable()]
    public class Segment : Texture3D
    {
        private String[] fileNames;
        private String[] names;
        private Bitmap bmp;
        int width, height, length;
        /// <summary>
        /// Constructor for the Segment class
        /// </summary>
        /// <param name="filenames">list of file names</param>
        /// <param name="names">texture names</param>
        /// <param name="format">textl format</param>
        public Segment(String[] filenames, String[] names, TexelFormat format)
            : base(names[0], 0,0,0, format)
        {
            this.fileNames = filenames;
            this.names = names;
            ReadHeader();
            this._width = width;
            this._height = height;
            this._depth = length;
        }
        
        
        #region File operations
        
        /// <summary>
        ///  LoadFromFile - static function that loads a Volume from a file
        /// using binary deserialization.  Returns null if these is a problem.
        /// </summary>
        /// <param name="filename">name of the file to load</param>
        /// <returns>Volume data</returns>
        public static Volume LoadFromFile(String filename)
        {
            Volume obj;

            Stream stream = File.Open(filename, FileMode.Open);
            BinaryFormatter formatter = new BinaryFormatter();

            try
            {
                obj = (Volume)formatter.Deserialize(stream);
            }
            catch
            {
                obj = null;
            }
            stream.Close();

            return obj;
        }

    
        /// <summary>
        /// SaveToFile - function that saves a transfer function to a file
        ///  using binary serialization.  This is not static and is simply called on the
        ///  object that needs to be saved
        /// </summary>
        /// <param name="filename"></param>
        public void SaveToFile(String filename)
        {
            //
            // Make a clone to save.  The marshalling done by remoting causes problems with 
            //  serialization.
            //
            Volume obj = (Volume)this.Clone();

            Stream stream = File.Open(filename, FileMode.Create);
            BinaryFormatter formatter = new BinaryFormatter();

            formatter.Serialize(stream, obj);
            stream.Close();
        }
        #endregion


        
        /// <summary>
        /// Implementation of Texture3D GetTexture Method
        /// </summary>
        /// <param name="xDim">x dimension</param>
        /// <param name="yDim">y dimension</param>
        /// <param name="zDim">z dimension</param>
        /// <returns>texture data</returns>
        public override byte[] GetTextureByte(out int xDim, out int yDim, out int zDim)
        {

            byte[] byteData = null;
            xDim = width;
            yDim = height;
            zDim = length;
            byteData = new byte[xDim * yDim * zDim*4];
            for (int j = 0; j < xDim * yDim * zDim*4; j++)
                byteData[j] = (byte)0;
                        
            for (int i = 0; i < zDim; i++)
            {
                if (!File.Exists(this.fileNames[i]))
                {
                    gLogger.Instance.writeLog("Cannot open file: ");
                    gLogger.Instance.writeLog(this.fileNames[i]);
                    gLogger.Instance.writeLog("\n");
                }

                else
                {
                    try
                    {
                        bmp = new Bitmap(fileNames[i]);
                        Color[] tempBuff = new Color[xDim * yDim];
                        for (int y = 0; y < yDim; y++)
                            for (int x = 0; x < xDim; x++)
                                tempBuff[y * xDim + x] = bmp.GetPixel(x, y);

                        for (int c = 0; c < xDim * yDim; c++)
                        {
                            byteData[xDim * yDim * i * 4 + 4 * c] =  tempBuff[c].R;
                            byteData[xDim * yDim * i * 4 + 4*c + 1] = tempBuff[c].G;
                            byteData[xDim * yDim * i * 4 + 4*c + 2] = tempBuff[c].B;
                            byteData[xDim * yDim * i * 4 + 4*c + 3] = tempBuff[c].R;
                        }

                    }

                    catch (EndOfStreamException e)
                    {
                        gLogger.Instance.writeLog("{0} caught and ignored. " +
                            "Using default values." + e.GetType().Name);
                    }
                    finally
                    {

                    }
                }
            }
            return byteData;

        }

        private void ReadHeader()
        {
            Bitmap bmp = new Bitmap(fileNames[0]);
            width = bmp.Width;
            height = bmp.Height;
            length = fileNames.Length;
        }

       
    }
}